﻿using System;
using System.Collections.Generic;
using System.Text;
using DhbMatrixAlgebra;
using FunctionalCLR;
using FunctionalCLR.Core;

namespace Zove.Library.Geometry {
    public class TetrahedronVolumeNode : FuncNode {

        public TetrahedronVolumeNode()
            : base() {
            base.Value = "volt";
        }

        public override FuncNode GetReversedFunction(int index) {
            throw new NoReversedOperatorException(string.Format(
                "Function {0} cannot be transformed", this.Value));
        }

        public override object Evaluate()
        {
            if (Parameters.Count < 12)
            {
                throw new ArgumentException(
                    "usage: volt(number1, ..., number12)");
            }

            return Volume(
                Convert.ToDouble(this.Parameters[0].Evaluate()),
                Convert.ToDouble(this.Parameters[1].Evaluate()),
                Convert.ToDouble(this.Parameters[2].Evaluate()),
                Convert.ToDouble(this.Parameters[3].Evaluate()),
                Convert.ToDouble(this.Parameters[4].Evaluate()),
                Convert.ToDouble(this.Parameters[5].Evaluate()),
                Convert.ToDouble(this.Parameters[6].Evaluate()),
                Convert.ToDouble(this.Parameters[7].Evaluate()),
                Convert.ToDouble(this.Parameters[8].Evaluate()),
                Convert.ToDouble(this.Parameters[9].Evaluate()),
                Convert.ToDouble(this.Parameters[10].Evaluate()),
                Convert.ToDouble(this.Parameters[11].Evaluate())
                ).ToString();
        }

        public double Volume(
            double a1, double a2, double a3,
            double b1, double b2, double b3,
            double c1, double c2, double c3,
            double d1, double d2, double d3) {
            Matrix n = new Matrix(new double[,]{
                {a1,b1,c1,d1},
                {a2,b2,c2,d2},
                {a3,b3,c3,d3},
                {1,1,1,1}
            });

            return Math.Abs(n.Determinant()) / 6;
        }
    }
}
